﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Wedo.Recognition.Domain.Models;
using Wedo.Recognition.Domain;
using Wedo.Recognition.Domain;
using Wedo.Service.Common;
using Wedo.Domain.Models;
using Wedo.Recognition.Repository;



namespace Wedo.Recognition.Service.Action
{
    /// <summary>
    /// 认款申请的逻辑处理
    /// </summary>
    public class PaymentService : BaseService<PaymentApply> 
    {

        public PaymentService(IUnitWork dbContext)
            : base(dbContext, dbContext.Set<PaymentApply>())
        {

        }

        /// <summary>
        /// 添加认款申请
        /// </summary>
        /// <param name="checkRecordId">签出记录</param>        
        /// <param name="checkItems">认款信息</param>
        /// <param name="checkMan">添加人</param>
        public void AddPayment(PaymentApply paymentApplyItem, List<PaymentAttach> attachList)
        {
            string applyMan = paymentApplyItem.ApplyMan;

            BankData bdItem = _dbContext.Set<BankData>()
                .Find(paymentApplyItem.BankDataId);

            paymentApplyItem.BankDataId = bdItem.Id;
            paymentApplyItem.Status = (int)ApprovalStatus.Waited;

            //客户和第一个认款必须相同
            string customerCode = bdItem.PaymentApplyCustomeCode();
            if (customerCode.IsNotNullOrWhiteSpace() && paymentApplyItem.CustomerCode != customerCode)
            {
                throw new Exception("客户和已认款的客户不同，你可以申请争议解决！");
            }

            CheckPayment(paymentApplyItem, bdItem);

            #region 数据处理

            var MyCheck = bdItem.CheckRecord.FirstOrDefault(m => m.ApplyMan == applyMan);
             //申请赋值
            paymentApplyItem.BankDataId = bdItem.Id;
            paymentApplyItem.CheckRecordID = MyCheck.Id;
            paymentApplyItem.ApplyTime = DateTime.Now;
            //paymentApplyItem.Approver = paymentApplyItem.ApplyMan;
            //paymentApplyItem.ApprovalTime = DateTime.Now;
            _repository.Create(paymentApplyItem);

            if (paymentApplyItem.ReleaseOrder.IsNotNullOrWhiteSpace())
            {
                //放单记录
                _dbContext.Set<ReleaseOrder>()
                    .Create(new ReleaseOrder()
                {
                    CustomerCode = paymentApplyItem.CustomerCode,
                    CustomerName = paymentApplyItem.CustomerName,
                    Amount = paymentApplyItem.Amount,
                    Percent = paymentApplyItem.Percent,

                    ApplyTime = paymentApplyItem.ApplyTime,
                    ApplyMan = paymentApplyItem.ApplyMan,
                    Approver = paymentApplyItem.ReleaseOrder,
                    ApprovalTime=DateTime.Now,
                    ModifiedBy = paymentApplyItem.ReleaseOrder,

                    CheckRecordID=paymentApplyItem.CheckRecordID,
                    PaymentApplyID=paymentApplyItem.Id,
                    
                    OrderNum = paymentApplyItem.OrderNum,
                    Status = (int)ApprovalStatus.Waited,
                    BankDataID = paymentApplyItem.BankDataId,
                    BankData = bdItem
                });
            }

            //添加认款附件
            if (attachList == null)
                attachList = new List<PaymentAttach>();
            attachList.ForEach(s =>
            {
                s.PaymentApplyId = paymentApplyItem.Id;
                s.Id = Guid.NewGuid();
                s.Status = (int)ApprovalStatus.Agree;
                _dbContext.Set<PaymentAttach>().Create(s);
            });
             
            
            #endregion

            Commit();
        }

        public override PaymentApply Update(PaymentApply entity)
        {
            var model = GetById(entity.Id);
            if (model.Status == 2)
                throw new Exception("认款已经被同意不能被修改！");

            BankData bdItem = _dbContext.Set<BankData>().Find(entity.BankDataId);
            CheckPayment(entity, bdItem);

            var firstPA = bdItem.PaymentApply.OrderBy(m=>m.Created).FirstOrDefault();
            if (firstPA != null && firstPA.Id != entity.Id)
            {
                if (entity.CustomerCode != bdItem.PaymentApplyCustomeCode())
                {
                    throw new Exception("客户和已认款的客户不同，你可以申请争议解决！");
                }
            }


            string sql = "delete from ReleaseOrder where CheckRecordID=@p0";
            _dbContext.ExSql(sql, entity.Id);
            
            if (entity.ReleaseOrder.IsNotNullOrWhiteSpace())
            {
                _dbContext.Set<ReleaseOrder>().Create(
                new ReleaseOrder()
                {
                    CustomerCode = entity.CustomerCode,
                    CustomerName = entity.CustomerName,
                    Amount = entity.Amount,
                    Percent = entity.Percent,

                    ApplyTime = entity.ApplyTime,
                    ApplyMan = entity.ApplyMan,
                    Approver = entity.ReleaseOrder,
                    ApprovalTime = DateTime.Now,
                    ModifiedBy = entity.ReleaseOrder,

                    CheckRecordID = entity.CheckRecordID,
                    PaymentApplyID = entity.Id,

                    OrderNum = entity.OrderNum,
                    Status = (int)ApprovalStatus.Waited,
                    BankDataID = entity.BankDataId,
                    BankData = bdItem
                });
            }


            entity.Created = model.Created;
            entity.CreatedBy = model.CreatedBy;
            entity.Modified = DateTime.Now;

            UpdateBefore(model, entity);
            _repository.UpdateProperties(model,entity);

            Commit();

            return model;
        }

        protected override void UpdateBefore(PaymentApply old, PaymentApply news)
        {
            news.ApplyTime = DateTime.Now;

            news.CheckRecordID = old.CheckRecordID;
            news.ApplyMan = old.ApplyMan;
            news.CreatedBy = old.CreatedBy;
            news.ModifiedBy = old.ModifiedBy;
            base.UpdateBefore(old, news);
        }

        /// <summary>
        /// 检查认款
        /// </summary>
        /// <param name="entity"></param>
        /// <param name="bdItem"></param>
        private void CheckPayment(PaymentApply entity, BankData bdItem)
        {
            string applyMan = entity.ApplyMan;

            if (entity.Amount <= 0)
                throw new Exception("认款金额必须大于0");

            //账单没有被签出
            if (bdItem.HasChecked(applyMan) == false)
                throw new Exception(Wedo.Recognition.Resources.ErrorMessage.Can_Checkout);

            //是否超过可认款余额
            if (bdItem.Remain() < entity.Amount)
                throw new Exception("认款总金额超出了剩余可认款，您可以为此申请争议处理");
            //客户必填
            if (string.IsNullOrWhiteSpace(entity.CustomerCode))
                throw new ArgumentException(Wedo.Recognition.Resources.ErrorMessage.Must_Fill_Information);


            if (entity.CustomerName == bdItem.Payer.Trim())
            {
                entity.Status = (int)ApprovalStatus.Agree;//默认同意
            }
            else
            {
                entity.Status = 1;//待审批
            }
        }
        
        /// <summary>
        /// 审批认款申请 ,默认同意，暂时不需要审批
        /// </summary>
        /// <param name="approveMan">审批人</param>
        /// <param name="paymentApplyId">
        /// 认款申请编号
        /// </param>
        public void ApprovePayment(string approveMan, Guid paymentApplyId)
        {
            PaymentApply applyItem = GetById(paymentApplyId);

            BankData bdItem = _dbContext.Set<BankData>()
                .Find(applyItem.BankDataId);

            if (bdItem.Remain() < applyItem.Amount)
                throw new Exception(Wedo.Recognition.Resources.ErrorMessage.Amount_Over);
 
            applyItem.Status = (int)ApprovalStatus.Agree;
            applyItem.Approver = approveMan;
            applyItem.ApprovalTime = DateTime.Now;

            Commit();
        }

        /// <summary>
        /// 拒绝认款申请 ,默认同意，暂时不需要审批
        /// </summary>
        /// <param name="approveMan">审批人</param>
        /// <param name="paymentApplyId">
        /// 认款申请编号
        /// </param>
        public void RejectPayment(string approveMan, Guid paymentApplyId)
        {

            BankDataService bankDataService = new BankDataService(_dbContext);
            PaymentApply applyItem =GetById(paymentApplyId);

            if (applyItem.Status == (int)ApprovalStatus.Reject)
                throw new  Exception(Wedo.Recognition.Resources.ErrorMessage.Has_Declied);

            if (applyItem.Status == (int)ApprovalStatus.Agree)
                throw new  Exception(Wedo.Recognition.Resources.ErrorMessage.Has_Declied);

            applyItem.Status = (int)ApprovalStatus.Reject;
            applyItem.Approver = approveMan;
            applyItem.ApprovalTime = DateTime.Now; 
            Commit();
        }

        /// <summary>
        /// 撤销认款申请
        /// </summary>
        /// <param name="applyMan">撤销人</param>
        /// <param name="paymentApplyId">
        /// 认款申请编号
        /// </param>
        public void CancelPayment(string applyMan, Guid paymentApplyId)
        {
            BankDataService bankDataService = new BankDataService(_dbContext);
            PaymentApply applyItem = GetById(paymentApplyId);//&& s.ApplyMan == applyMan
            
            if (applyItem.Status > 1)
                throw new Exception("审批认款后不能取消,你可以通过争议解决！");

             _repository.Delete(applyItem); 
            Commit();
        }

        public override void Remove(object id)
        {
            var model = base.GetById(id);
            if (model == null)
                throw new Exception("没有此数据");

            var realeasOrder = _dbContext.Set<ReleaseOrder>()
                .Find(m => m.PaymentApplyID == model.Id);
            if (realeasOrder != null)
            {
                _dbContext.Set<ReleaseOrder>().Delete(realeasOrder);
            }
            _dbContext.Set<PaymentApply>().Delete(model);

            Commit();
        }

        public IQueryable<PaymentApply> GetQuery(CommonSearchModel where)
        {
            var query = GetAll(includes: "BankData");
            if (where.StartTime != null)
            {
                DateTime Start = where.StartTime.Value;
                query = query.Where(m => m.ApplyTime > Start);
            }
            if (where.EndTime != null)
            {
                DateTime endTime = where.EndTime.Value.AddDays(1);
                query = query.Where(m => m.ApplyTime < endTime);
            }

            if (where.Status != null)
                query = query.Where(m => m.Status == where.Status);

            //if (where.IsApproved.HasValue)
            //{
            //    if (where.IsApproved == true)
            //    {
            //        query = query.Where(m => m.Status > 1);
            //    }
            //    else {
            //        query = query.Where(m => m.Status == 1);
            //    }
            //}

            if (where.ApplyMan.IsNotNullOrWhiteSpace())
            {
                query = query.Where(m => m.ApplyMan == where.ApplyMan);
            }
            if (where.Keyword.IsNotNullOrWhiteSpace())
            {
                query = query.Where(m => m.BankData.Assiginment.Contains(where.Keyword));
            }
            return query;
        }
    }
}  